package com.fkcai.hansoul.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fkcai.hansoul.common.constant.UserConstant;
import com.fkcai.hansoul.common.exception.ComFoundException;
import com.fkcai.hansoul.common.util.ResultCode;
import com.fkcai.hansoul.common.util.SensitiveWordFilterUtil;
import com.fkcai.hansoul.common.util.ThreadLocalUtil;
import com.fkcai.hansoul.mapper.PostCommentMapper;
import com.fkcai.hansoul.mapper.PostCommentReplyMapper;
import com.fkcai.hansoul.mapper.UserMapper;
import com.fkcai.hansoul.model.dto.post.PostCommentDto;
import com.fkcai.hansoul.model.dto.post.PostCommentReplyDto;
import com.fkcai.hansoul.model.entity.PostComment;
import com.fkcai.hansoul.model.entity.PostCommentReply;
import com.fkcai.hansoul.model.entity.User;
import com.fkcai.hansoul.model.vo.post.PostCommentReplyVo;
import com.fkcai.hansoul.model.vo.post.PostCommentVo;
import com.fkcai.hansoul.service.CommentReplyService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.awt.print.Pageable;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 评论，回复服务实现类
 */
@Service
public class CommentReplyServiceImpl implements CommentReplyService {
	@Autowired
	private PostCommentMapper postCommentMapper;
	@Autowired
	private PostCommentReplyMapper postCommentReplyMapper;
	@Autowired
	private UserMapper userMapper;
	
	/**
	 * 创建帖子评论
	 *
	 * @param postCommentDto 帖子评论参数
	 * @return 帖子评论信息
	 */
	@Override
	@Transactional(
			propagation = Propagation.REQUIRED,
			isolation = Isolation.READ_COMMITTED,
			rollbackFor = Exception.class
	)
	public PostCommentVo createPostComment (PostCommentDto postCommentDto) {
		// 创建帖子评论
		PostComment postComment = new PostComment();
		
		postComment.setPostId(postCommentDto.getPostId());
		postComment.setAuthorId(postCommentDto.getAuthorId());
		postComment.setContent(SensitiveWordFilterUtil.replaceSensitiveWords(postCommentDto.getContent()));
		postComment.setCreateTime(LocalDateTime.now());
		postComment.setReplyCount(0);
		postComment.setStatus("normal");
		
		postCommentMapper.insert(postComment);
		
		// 获取评论者信息
		User author = getAuthorId(postCommentDto.getAuthorId());
		
		// 返回帖子评论信息
		return PostCommentVo.fromPostComment(postComment, author);
	}
	
	
	/**
	 * 获取帖子评论
	 *
	 * @param postId 帖子 id
	 * @param page   页码
	 * @param size   分页大小
	 * @return 帖子评论信息
	 */
	@Override
	@Transactional(readOnly = true)
	public Page<PostCommentVo> getPostCommentByPostId (Integer postId, int page, int size) {
		// 创建分页对象
		Page<PostComment> pageParam = new Page<>(page, size);
		
		// 构建查询条件
		LambdaQueryWrapper<PostComment> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(PostComment::getPostId, postId)
				.eq(PostComment::getStatus, "normal") // 只查询正常状态
				.orderByDesc(PostComment::getCreateTime); // 按时间倒序
		
		// 执行分页查询
		Page<PostComment> postCommentPage = postCommentMapper.selectPage(pageParam, queryWrapper);
		List<PostComment> postCommentList = postCommentPage.getRecords();
		
		// 没有数据就返回空页
		if (postCommentList.isEmpty()) return new Page<>(page, size, postCommentPage.getTotal());
		
		// 收集评论者 id
		Set<Integer> userIds = postCommentList
				.stream()
				.map(PostComment::getAuthorId)
				.collect(Collectors.toSet());
		
		// 批量查询用户信息
		List<User> users = userMapper.selectList(
				new LambdaQueryWrapper<User>()
						.in(User::getUserId, userIds)
		);
		
		// 将用户信息转换为 Map
		Map<Integer, User> userMap = users.stream()
				.collect(Collectors
						.toMap(User::getUserId, Function.identity())
				);
		
		// 转换为 vo
		List<PostCommentVo> vos = postCommentList.stream().map(postComment -> {
			PostCommentVo vo = new PostCommentVo();
			BeanUtils.copyProperties(postComment, vo);
			
			// 获取评论者信息
			User author = userMap.get(postComment.getAuthorId());
			if (author != null) {
				vo.setAuthor(PostCommentVo.UserInfo.fromUser(author));
			}
			
			return vo;
		}).collect(Collectors.toList());
		
		Page<PostCommentVo> resultPage = new Page<>(page, size, postCommentPage.getTotal());
		resultPage.setRecords(vos);
		
		return resultPage;
	}
	
	
	/**
	 * 创建帖子评论回复
	 *
	 * @param postCommentReplyDto 帖子评论回复参数
	 * @return 帖子评论回复信息
	 */
	@Override
	@Transactional(
			propagation = Propagation.REQUIRED,
			isolation = Isolation.READ_COMMITTED,
			rollbackFor = Exception.class
	)
	public PostCommentReplyVo createPostCommentReply (PostCommentReplyDto postCommentReplyDto) {
		// 验证评论是否存在
		PostComment postComment = postCommentMapper.selectById(postCommentReplyDto.getCommentId());
		
		if (postComment == null || "DELETED".equals(postComment.getStatus()))
			throw new ComFoundException(ResultCode.POST_COMMENT_NOT_EXIST);
		
		// 创建帖子评论回复
		PostCommentReply commentReply = new PostCommentReply();
		
		commentReply.setCommentId(postCommentReplyDto.getCommentId());
		commentReply.setAuthorId(postCommentReplyDto.getAuthorId());
		commentReply.setContent(SensitiveWordFilterUtil.replaceSensitiveWords(postCommentReplyDto.getContent()));
		commentReply.setRepliedUserId(postCommentReplyDto.getRepliedUserId());
		commentReply.setCreateTime(LocalDateTime.now());
		commentReply.setLikeCount(0);
		commentReply.setReportCount(0);
		commentReply.setStatus("NORMAL");
		
		// 插入评论回复
		postCommentReplyMapper.insert(commentReply);
		
		// 更新帖子评论回复数
		postComment.setReplyCount(postComment.getReplyCount() + 1);
		postCommentMapper.updateById(postComment);
		
		// 获取作者和被回复用户信息
		User author = userMapper.selectById(commentReply.getAuthorId());
		User repliedUser = userMapper.selectById(commentReply.getRepliedUserId());
		
		return PostCommentReplyVo.fromReply(commentReply, author, repliedUser);
	}
	
	/**
	 * 获取帖子评论回复
	 *
	 * @param commentId 帖子 id
	 * @param page      页码
	 * @param size      分页大小
	 * @return 帖子评论回复信息
	 */
	@Override
	@Transactional(readOnly = true)
	public Page<PostCommentReplyVo> getPostCommentReplyByPostId (Integer commentId, int page, int size) {
		Page<PostCommentReply> pageParam = new Page<>(page, size);
		
		// 构建查询条件
		LambdaQueryWrapper<PostCommentReply> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(PostCommentReply::getCommentId, commentId)
				.eq(PostCommentReply::getStatus, "NORMAL")
				.orderByAsc(PostCommentReply::getCreateTime);
		
		// 分页查询
		Page<PostCommentReply> replyPage = postCommentReplyMapper.selectPage(pageParam, queryWrapper);
		List<PostCommentReply> replyList = replyPage.getRecords();
		
		// 没有数据就返回空页
		if (replyList.isEmpty()) return new Page<>(page, size, replyPage.getTotal());
		
		// 收集用户 id
		HashSet<Integer> userIds = new HashSet<>();
		replyList.forEach(reply -> {
			userIds.add(reply.getAuthorId());
			userIds.add(reply.getRepliedUserId());
		});
		
		// 查询用户信息
		List<User> users = userMapper.selectList(
				new LambdaQueryWrapper<User>()
						.in(User::getUserId, userIds)
		);
		
		// 将用户信息转换为 Map
		Map<Integer, User> userMap = users.stream()
				.collect(Collectors
						.toMap(User::getUserId, Function.identity())
				);
		
		// 转换为 vo
		List<PostCommentReplyVo> vos = replyList.stream().map(reply -> {
			PostCommentReplyVo vo = new PostCommentReplyVo();
			BeanUtils.copyProperties(reply, vo);
			
			// 获取评论者信息
			User author = userMap.get(reply.getAuthorId());
			if (author != null) vo.setAuthor(PostCommentReplyVo.UserInfo.fromUser(author));
			
			// 获取被回复用户信息
			User repliedUser = userMap.get(reply.getRepliedUserId());
			if (repliedUser != null) vo.setRepliedUser(PostCommentReplyVo.UserInfo.fromUser(repliedUser));
			
			return vo;
		}).collect(Collectors.toList());
		
		// 返回分页结果
		Page<PostCommentReplyVo> resultPage = new Page<>(page, size, replyPage.getTotal());
		resultPage.setRecords(vos);
		
		return resultPage;
	}
	
	
	/* =========同用方法========= */
	
	/**
	 * 获取当前用户 id, 即帖子创建者 id
	 *
	 * @return 当前用户 id
	 */
	public User getAuthorId (Integer authorId) {
		// 检验用户状态
		User user = userMapper.selectById(authorId);
		
		if (user == null) throw new ComFoundException(ResultCode.USER_NOT_EXIST);
		if (user.getAccountStatus() == UserConstant.DISABLED)
			throw new ComFoundException(ResultCode.USER_ACCOUNT_ANOMALY);
		
		return user;
	}
	
}
